/**
 * 该插件可根据菜单配置自动生成 ANTD menu组件
 * menuData示例：
 * [
 *  {
 *    title: '菜单标题',
 *    icon: '菜单图标',
 *    path: '菜单路由',
 *    invisible: 'boolean, 是否不可见',
 *    children: [子菜单配置]
 *  },
 *  {
 *    title: '菜单标题',
 *    icon: '菜单图标',
 *    path: '菜单路由',
 *    invisible: 'boolean, 是否不可见',
 *    children: [子菜单配置]
 *  }
 * ]
 **/
import Menu from "ant-design-vue/es/menu";
import Icon from "ant-design-vue/es/icon";

const { Item, SubMenu } = Menu;

// 默认菜单图标数组，如果菜单没配置图标，则会设置从该数组随机取一个图标配置
const iconArr = [
  "dashboard",
  "user",
  "form",
  "setting",
  "message",
  "safety",
  "bell",
  "delete",
  "code-o",
  "poweroff",
  "eye-o",
  "hourglass"
];

export default {
  name: "IMenu",
  props: {
    menuData: {
      type: Array,
      required: true
    },
    theme: {
      type: String,
      required: false,
      default: "dark"
    },
    mode: {
      type: String,
      required: false,
      default: "inline"
    },
    collapsed: {
      type: Boolean,
      required: false,
      default: false
    }
  },
  data() {
    return {
      openKeys: [],
      selectedKeys: [],
      cachedOpenKeys: []
    };
  },
  computed: {
    rootSubmenuKeys: vm => {
      let keys = [];
      vm.menuData.forEach(item => {
        keys.push(item.path);
      });
      return keys;
    }
  },
  created() {
    this.updateMenu();
  },
  watch: {
    collapsed(val) {
      if (val) {
        this.cachedOpenKeys = this.openKeys;
        this.openKeys = [];
      } else {
        this.openKeys = this.cachedOpenKeys;
      }
    },
    $route: function() {
      this.updateMenu();
    }
  },
  methods: {
    renderIcon: function(h, icon) {
      return icon === "none"
        ? null
        : h(Icon, {
            props: {
              type:
                icon !== undefined
                  ? icon
                  : iconArr[Math.floor(Math.random() * iconArr.length)]
            }
          });
    },
    renderMenuItem: function(h, menu, pIndex, index) {
      return h(
        Item,
        {
          key: menu.path ? menu.path : "item_" + pIndex + "_" + index
        },
        [
          h("a", { attrs: { href: "#" + menu.path } }, [
            this.renderIcon(h, menu.icon),
            h("span", [menu.name])
          ])
        ]
      );
    },
    renderSubMenu: function(h, menu, pIndex, index) {
      var this2_ = this;
      var subItem = [
        h("span", { slot: "title" }, [
          this.renderIcon(h, menu.icon),
          h("span", [menu.name])
        ])
      ];
      var itemArr = [];
      var pIndex_ = pIndex + "_" + index;
      menu.children.forEach(function(item, i) {
        itemArr.push(this2_.renderItem(h, item, pIndex_, i));
      });
      return h(
        SubMenu,
        { key: menu.path ? menu.path : "submenu_" + pIndex + "_" + index },
        subItem.concat(itemArr)
      );
    },
    renderItem: function(h, menu, pIndex, index) {
      if (!menu.invisible) {
        return menu.children
          ? this.renderSubMenu(h, menu, pIndex, index)
          : this.renderMenuItem(h, menu, pIndex, index);
      }
    },
    renderMenu: function(h, menuTree) {
      var this2_ = this;
      var menuArr = [];
      menuTree.forEach(function(menu, i) {
        menuArr.push(this2_.renderItem(h, menu, "0", i));
      });
      return menuArr;
    },
    onOpenChange(openKeys) {
      const latestOpenKey = openKeys.find(
        key => this.openKeys.indexOf(key) === -1
      );
      if (this.rootSubmenuKeys.indexOf(latestOpenKey) === -1) {
        this.openKeys = openKeys;
      } else {
        this.openKeys = latestOpenKey ? [latestOpenKey] : [];
      }
    },
    updateMenu() {
      let routes = this.$route.matched.concat();
      this.selectedKeys = [routes.pop().path];
      let openKeys = [];
      routes.forEach(item => {
        openKeys.push(item.path);
      });
      this.collapsed || this.mode === "horizontal"
        ? (this.cachedOpenKeys = openKeys)
        : (this.openKeys = openKeys);
    }
  },
  render(h) {
    return h(
      Menu,
      {
        props: {
          theme: this.$props.theme,
          mode: this.$props.mode,
          openKeys: this.openKeys,
          selectedKeys: this.selectedKeys
        },
        on: {
          openChange: this.onOpenChange,
          select: obj => {
            this.selectedKeys = obj.selectedKeys;
            this.$emit("select", obj);
          }
        }
      },
      this.renderMenu(h, this.menuData)
    );
  }
};
